package org.totoro;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;

import java.util.HashMap;
import java.util.Map;

/**
 * 定义队列和交换机
 *
 * @author daocr
 * @date 2020/8/13
 */
public class Declare {


    RabbitAdmin rabbitAdmin;


    /**
     * 定义普通队列
     */
    public void declareQueue() {
        String queueNormalName = "my_queue";
        /**
         <pre>
         参数1：队列名称
         参数2：是否持久化              默认值  ：true
         参数3：是否是专属队列          默认值 : false
         参数4：是否自动删除            默认值 : false
         </pre>
         */
        Queue queue = new Queue(queueNormalName, true, false, false);

        // 构建模式：创建
        QueueBuilder my_queue = QueueBuilder.durable("my_queue");

        rabbitAdmin.declareQueue(queue);
    }

    /**
     * TTL消息队列配置，其实还是用死信队列实现的
     *
     * @return
     */
    public void messageTtlQueue() {
        QueueBuilder
                .durable("my_queue")
                // 配置到期后转发的交换
                .withArgument("x-dead-letter-exchange", "my_exchange")
                // 配置到期后转发的路由键
                .withArgument("x-dead-letter-routing-key", "order_timeout*")
                .build();
    }


    /**
     * 定义死信队列
     */
    public void declareDealQueue() {

        //交换机路由key
        String dead_exchange_routing_key = "normal-queue-001-fail-routing-key";
        // 交换机名称
        String topicName = "normal.queue.topic";

        //设置死信交换机
        //设置死信routingKey
        Map<String, Object> queueArgs = new HashMap<>();
        queueArgs.put("x-dead-letter-exchange", topicName);
        queueArgs.put("x-dead-letter-routing-key", dead_exchange_routing_key);
        queueArgs.put("origin", "test");

        String queueNormalName = "my_queue";
        Queue queue = new Queue(queueNormalName, true, false, false, queueArgs);
        rabbitAdmin.declareQueue(queue);
    }


    /**
     * 将路由键和某模式进行匹配。
     * <p>
     * 此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词，符号“*”只能匹配一个词。
     * <p>
     * 是否支持路由：是
     */
    public void topicExchange() {

        TopicExchange myTopicExchange = (TopicExchange) ExchangeBuilder.topicExchange("my_topic_exchange").build();

        // 定义交换机
        rabbitAdmin.declareExchange(myTopicExchange);

        // 绑定交换机
        Binding with = BindingBuilder.bind(new Queue("my_queue")).to(myTopicExchange).with("order_*");
        rabbitAdmin.declareBinding(with);
    }

    /**
     * Fanout 不处理路由键。你只需要简单的将队列绑定到交换机上。
     * 一个发送到该类型交换机的消息都会被广播到与该交换机绑定的所有队列上。
     * <p>
     * 是否支持路由：否
     */
    public void fanoutExchange() {
        FanoutExchange myTopicExchange = (FanoutExchange) ExchangeBuilder.fanoutExchange("my_fanout_exchange").build();


    }

    /**
     * 处理路由键，需要将一个队列绑定到交换机上，要求该消息与一个特定的路由键完全匹配。
     * <p>
     * 这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键为 “green”，则只有路由键为“green”的消息才被转发，不会转发路由键为"red"，只会转发路由键为"green"。
     * <p>
     * 是否支持路由：否
     */
    public void directExchange() {
        DirectExchange myTopicExchange = (DirectExchange) ExchangeBuilder.directExchange("my_direct_exchange").build();
    }

    /**
     * 不处理路由键，而是根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对；
     * 当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配；
     * 如果完全匹配则消息会路由到该队列，否则不会路由到该队列。
     * headers属性是一个键值对，可以是Hashtable，键值对的值可以是任何类型。
     * 而fanout，direct，topic 的路由键都需要要字符串形式的
     * <p>
     * 是否支持路由：否
     */
    public void headersExchangeExchange() {
        HeadersExchange headersExchange = (HeadersExchange) ExchangeBuilder.directExchange("my_header_exchange").build();
    }


}
